package config

import (
	"fmt"
	"go.uber.org/zap"

	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

var GlobalConf = new(ServerConfig)

// ServerConfig 全局配置信息
type ServerConfig struct {
	Name        string      `mapstructure:"name"`
	Port        int         `mapstructure:"port"`
	Mode        string      `mapstructure:"mode"`
	MysqlConfig MySQLParams `mapstructure:"mysql"`
	RedisConfig RedisParams `mapstructure:"redis"`
	LogConfig   LogParams   `mapstructure:"log"`
	MeiliConfig MeiliParams `mapstructure:"search"`
}

// LogParams 日志全局配置
type LogParams struct {
	Level      string `mapstructure:"level"`
	Filename   string `mapstructure:"filename"`
	MaxSize    int    `mapstructure:"max_size"`
	MaxAge     int    `mapstructure:"max_age"`
	MaxBackups int    `mapstructure:"max_backups"`
}

// RedisParams Redis Viper
type RedisParams struct {
	Host string `mapstructure:"host"`
	Port int    `mapstructure:"port"`
	DB   int    `mapstructure:"db"`
}

// MySQLParams  Viper
type MySQLParams struct {
	Host        string `mapstructure:"host"`
	Username    string `mapstructure:"username"`
	Password    string `mapstructure:"password"`
	Port        string `mapstructure:"port"`
	DBName      string `mapstructure:"dbname"`
	Charset     string `mapstructure:"charset"`
	ParseTime   bool   `mapstructure:"parsetime"`
	MaxIdleConn int
	MaxOpenConn int
	LogMode     string `mapstructure:"logmode"`
}

// MeiliSearch Config
type MeiliParams struct {
	Host   string `mapstructure:"host"`
	ApiKey string `mapstructure:"apikey"`
}

// InitialConfiguration 初始化Viper配置信息
func InitialConfiguration() (err error) {
	v := viper.New()
	// 设置配置文件路径
	v.SetConfigName("settings")
	v.SetConfigType("yaml")
	v.AddConfigPath("./config")
	err = v.ReadInConfig()
	if err != nil {
		return err
	}
	// 配置信息反序列化
	if err := v.Unmarshal(GlobalConf); err != nil {
		zap.S().Errorf("viper unmarshal failed: %s", err.Error())
	}
	// 开始监听配置文件
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		fmt.Println("Config Change  Reload")
		if err := v.Unmarshal(GlobalConf); err != nil {
			fmt.Printf("viper.Unmarshal failed, err:%v\n", err)
		}
	})
	return nil
}
